package edu.uwo.se2.group3mapapp;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestFactory;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.util.Log;

 


import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.api.client.http.GenericUrl;


public class MapActivity extends Activity {
	boolean satView = false;
	LocationManager service;
	boolean enabledGPS;
	GoogleMap map;
	//auto complete references
	private ArrayList<String> referenceList;
	private ArrayList<Place> places;
	private List<FriendLocation> fl;
	//Repeat event stuff
	private final int REPEAT_EVENT = 30000;
	private Handler mRepeatEvent;

	private int userId = -1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = getIntent();
        userId = intent.getIntExtra(LoginActivity.USER_ID, -1);
        //getSupportFragmentManager().beginTransaction().add(android.R.id.content, fragment).commit();
        setContentView(R.layout.activity_map);
        service = (LocationManager) getSystemService(LOCATION_SERVICE);
        enabledGPS = service.isProviderEnabled(LocationManager.GPS_PROVIDER);
        
        
        
        //Init map
        map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
                .getMap();
        map.setMyLocationEnabled(true);
        //Set map to current location
        map.setMyLocationEnabled(true);  

		Criteria criteria = new Criteria();
		String provider = service.getBestProvider(criteria, false);
        Location location = service.getLastKnownLocation(provider);
        
        double lat = 0;
        double lng = 0;
        if (location != null) {
        	lat =  location.getLatitude();
        	lng = location.getLongitude();
        }
		CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(lat,lng));
		CameraUpdate zoom = CameraUpdateFactory.zoomTo(15);
		map.moveCamera(center);
		map.animateCamera(zoom);

		//Map click listener
		map.setOnMapLongClickListener(new GoogleMap.OnMapLongClickListener() {

			@Override
			public void onMapLongClick(final LatLng arg0) {
				// TODO Auto-generated method stub
				AlertDialog.Builder alert = new AlertDialog.Builder(MapActivity.this);

				alert.setTitle("Add Favorite");
				alert.setMessage("Enter a name");

				// Set an EditText view to get user input 
				final EditText input = new EditText(MapActivity.this);
				alert.setView(input);

				alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
						Editable value = input.getText();
						String valuestr = value.toString();
						map.addMarker(new MarkerOptions()
						.position(arg0)
						.title(valuestr)
						.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW)));
						new AddFavoriteTask().execute(
								valuestr,
								"",
								String.valueOf(arg0.latitude),
								String.valueOf(arg0.longitude));
					}
				});

				alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
						// Canceled.
					}
				});

				alert.show();

			}
		}); 

		map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
			
			@Override
			public boolean onMarkerClick(final Marker marker) {
				AlertDialog.Builder alert = new AlertDialog.Builder(MapActivity.this);

				alert.setTitle("Manage " + marker.getTitle());
				alert.setMessage("Update or delete this favorite.");
				
				// Set an EditText view to get user input 
				final EditText input = new EditText(MapActivity.this);
				alert.setView(input);
				alert.setPositiveButton("Update", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
						Editable value = input.getText();
						String valuestr = value.toString();
						//map.addMarker(new MarkerOptions().position(arg0).title(valuestr));
						String oldname = marker.getTitle();
						marker.setTitle(valuestr);
						new AddFavoriteTask().execute(
								valuestr,
								oldname,
								String.valueOf(marker.getPosition().latitude),
								String.valueOf(marker.getPosition().longitude));
					}
				});

				alert.setNeutralButton("Delete", new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						new DeleteFavoriteTask().execute(marker.getTitle());
						marker.remove();
						
					}
				});
				
				alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int whichButton) {
						// Canceled.
					}
				});
				
				alert.show();
				
				return true;
			}
		});
		
		//initializes auto complete
		AutoCompleteTextView mapSearchBox = (AutoCompleteTextView) findViewById(R.id.mapSearchBox);
		mapSearchBox.setAdapter(new PlacesAutoCompleteAdapter(this, R.layout.list_item));
		mapSearchBox.setOnItemClickListener(new OnItemClickListener() {
		      public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
		    	  String locationReference = referenceList.get(position);
		    	  new getPlaceDetails().execute(locationReference);
		    	  
		}
		});
		//Load POIs
	    new loadLocalPOIs().execute();
	    new GetFriendLocationsTask().execute();
	    new GetFavoritesTask().execute();
    } // end on create
    
    @Override
    public void onResume () {
    	super.onResume();
		mRepeatEvent = new Handler();
	    mRepeatEvent.postDelayed(doRepeatEvent, REPEAT_EVENT);
    	
	    map.clear();
	    
    	if(places != null){
			for(Place p: places){
				map.addMarker(new MarkerOptions()
		        .position(new LatLng(p.latitude, p.longitude))
		        .title(p.name));
			}
		}
    	
    	if (fl != null) {
	    	for (FriendLocation fr: fl) {
				map.addMarker(new MarkerOptions()
		        .position(new LatLng(fr.lat, fr.lng))
		        .title(fr.name)
		        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
			}
    	}
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.map, menu);
        return true;
    }
    
    public boolean onOptionsItemSelected(MenuItem item){
        switch (item.getItemId()){
        	case R.id.menu_logout:
        		Intent loginAct = new Intent(MapActivity.this, LoginActivity.class);
	            finish();
	            startActivity(loginAct);
	            return true;
        	case R.id.menu_toggle_map:
        		//map type 1 = normal, map type 2 = satellite, map type 3 = terrain
    			if(map.getMapType() == 1){
    				map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
    			}else{
    				map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
    			}
        		return true;
        	case R.id.menu_me:
        		if (enabledGPS) {
        		    map.setMyLocationEnabled(true);  
        			Criteria criteria = new Criteria();
        			String provider = service.getBestProvider(criteria, false);
        	        Location location = service.getLastKnownLocation(provider);
        	        double lat =  location.getLatitude();
        	        double lng = location.getLongitude();
        	        CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(lat,lng));
    	            CameraUpdate zoom = CameraUpdateFactory.zoomTo(15);
    	            map.moveCamera(center);
    	            map.animateCamera(zoom);
        		} else {
        			Toast.makeText(this, "GPS signal not found", Toast.LENGTH_LONG).show();
        		}
        		return true;
        	case R.id.menu_friends:
        		Intent friends = new Intent(MapActivity.this, FriendsActivity.class);
        		friends.putExtra(LoginActivity.USER_ID, userId);
	            startActivity(friends);
        		return true;
        	case R.id.menu_settings:
        		Intent settings = new Intent(MapActivity.this, SettingsActivity.class);
	            startActivity(settings);
        		return true;
        }
        return false;
	}
    //Handles auto complete results
  	private class PlacesAutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
  		private ArrayList<String> resultList;
  	    public PlacesAutoCompleteAdapter(Context context, int textViewResourceId) {
  	        super(context, textViewResourceId);
  	    }
  	    
  	    @Override
  	    public int getCount() {
  	        return resultList.size();
  	    }

  	    @Override
  	    public String getItem(int index) {
  	        return resultList.get(index);
  	    }

  	    @Override
  	    public Filter getFilter() {
  	        Filter filter = new Filter() {
  	            @Override
  	            protected FilterResults performFiltering(CharSequence constraint) {
  	                FilterResults filterResults = new FilterResults();
  	                if (constraint != null) {
  	                    // Retrieve the autocomplete results.
  	                    resultList = autocomplete(constraint.toString());
  	                    
  	                    // Assign the data to the FilterResults
  	                    filterResults.values = resultList;
  	                    filterResults.count = resultList.size();
  	                }
  	                return filterResults;
  	            }

  	            @Override
  	            protected void publishResults(CharSequence constraint, FilterResults results) {
  	                if (results != null && results.count > 0) {
  	                    notifyDataSetChanged();
  	                }
  	                else {
  	                    notifyDataSetInvalidated();
  	                }
  	            }};
  	        return filter;
  	    }
  	}
  	//Queries google for search input
    private ArrayList<String> autocomplete(String input) {
    	ArrayList<String> resultList = null;
        String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place/autocomplete/json?";
        HttpURLConnection conn = null;
        StringBuilder jsonResults = new StringBuilder();
        try {
        	//Get location
        	Criteria criteria = new Criteria();
    		String provider = service.getBestProvider(criteria, false);
        	Location location = service.getLastKnownLocation(provider);
    		double lat =  location.getLatitude();
    		double lng = location.getLongitude();
        	
    		//Build URL
            StringBuilder sb = new StringBuilder(PLACES_API_BASE);
            sb.append("&location=");
            sb.append(Double.toString(lat));
            sb.append(",");
            sb.append(Double.toString(lng));
            sb.append("&radius=3000");
            sb.append("&sensor=true");
            sb.append("&components=country:us");
            sb.append("&key=AIzaSyA5uyX7CyQkXa2q2LGqbWS9EJcu7HYX-Y0");
            sb.append("&input=" + URLEncoder.encode(input, "utf8"));
                      
            URL url = new URL(sb.toString());
            conn = (HttpURLConnection) url.openConnection();
            InputStreamReader in = new InputStreamReader(conn.getInputStream());
            
            // Load the results into a StringBuilder
            int read;
            char[] buff = new char[1024];
            while ((read = in.read(buff)) != -1) {
                jsonResults.append(buff, 0, read);
            }
        } catch (MalformedURLException e) {
            Log.e("Error", "Error processing Places API URL", e);
        } catch (IOException e) {
            Log.e("Error", "Error connecting to Places API", e);
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
        try {
            // Create a JSON object hierarchy from the results
            JSONObject jsonObj = new JSONObject(jsonResults.toString());
            JSONArray predsJsonArray = jsonObj.getJSONArray("predictions");
            
            // Extract the Place descriptions from the results
            resultList = new ArrayList<String>(predsJsonArray.length());
            referenceList = new ArrayList<String>(predsJsonArray.length());
            for (int i = 0; i < predsJsonArray.length(); i++) {
                resultList.add(predsJsonArray.getJSONObject(i).getString("description"));
                referenceList.add(predsJsonArray.getJSONObject(i).getString("reference"));
                
            }
        } catch (JSONException e) {
            Log.e("Error", "Cannot process JSON results", e);
        }
        return resultList;
    }
    //Grabs a specific places lat/lng based off of their reference id and goes to the location
    public class getPlaceDetails extends AsyncTask<String, Void, double[]>{
		@Override
		protected double[] doInBackground(String... params) {
			String reference = params[0];
	        String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place/details/json?";
	        HttpURLConnection conn = null;
	        StringBuilder jsonResults = new StringBuilder();
	        double[] coords = new double[2];
	        try {
	        	
	    		//Build URL
	            StringBuilder sb = new StringBuilder(PLACES_API_BASE);
	            sb.append("&sensor=false");
	            sb.append("&key=AIzaSyA5uyX7CyQkXa2q2LGqbWS9EJcu7HYX-Y0");
	            sb.append("&reference=" + URLEncoder.encode(reference, "utf8"));
	                      
	            URL url = new URL(sb.toString());
	            conn = (HttpURLConnection) url.openConnection();
	            InputStreamReader in = new InputStreamReader(conn.getInputStream());
	            
	            // Load the results into a StringBuilder
	            int read;
	            char[] buff = new char[1024];
	            while ((read = in.read(buff)) != -1) {
	                jsonResults.append(buff, 0, read);
	            }
	        } catch (MalformedURLException e) {
	            Log.e("Error", "Error processing Places API URL", e);
	        } catch (IOException e) {
	            Log.e("Error", "Error connecting to Places API", e);
	        } finally {
	            if (conn != null) {
	                conn.disconnect();
	            }
	        }
	        try {
	            // Create a JSON object hierarchy from the results
	            JSONObject jsonObj = new JSONObject(jsonResults.toString());
	            JSONObject result = jsonObj.getJSONObject("result");
	            JSONObject geometry = result.getJSONObject("geometry");
	            JSONObject location = geometry.getJSONObject("location");
	            
	            //Extract lat/lng from array
	            double lat = location.getDouble("lat");
	            double lng = location.getDouble("lng");
	            coords[0] = lat;
	            coords[1] = lng;
	            
	        } catch (JSONException e) {
	            Log.e("Error", "Cannot process JSON results", e);
	        }
	        return coords;
		}
		@Override
		protected void onPostExecute(double[] coords) {
			CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(coords[0],coords[1]));
			CameraUpdate zoom = CameraUpdateFactory.zoomTo(15);
			map.moveCamera(center);
			map.animateCamera(zoom);
		}
    }
    //Loads LOIs local to given GPS coords
    public class loadLocalPOIs extends AsyncTask<String, Void, ArrayList<Place>>{
		@Override
		protected ArrayList<Place> doInBackground(String... params) {
	        String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?";
	        HttpURLConnection conn = null;
	        StringBuilder jsonResults = new StringBuilder();
	        places = new ArrayList<Place>();
	        try { 	
	        	//Get location
	        	Criteria criteria = new Criteria();
	    		String provider = service.getBestProvider(criteria, false);
	        	Location location = service.getLastKnownLocation(provider);
	        	double lat = 0;
	        	double lng = 0;
	        	if (location != null) {
	        		lat =  location.getLatitude();
	    			lng = location.getLongitude();
	        	}
	    		//Build URL
	            StringBuilder sb = new StringBuilder(PLACES_API_BASE);
	            sb.append("&location=");
	            sb.append(Double.toString(lat));
	            sb.append(",");
	            sb.append(Double.toString(lng));
	            sb.append("&radius=15000");
	            sb.append("&sensor=true");
	            sb.append("&key=AIzaSyA5uyX7CyQkXa2q2LGqbWS9EJcu7HYX-Y0");
	                      
	            URL url = new URL(sb.toString());
	            conn = (HttpURLConnection) url.openConnection();
	            InputStreamReader in = new InputStreamReader(conn.getInputStream());
	            
	            // Load the results into a StringBuilder
	            int read;
	            char[] buff = new char[1024];
	            while ((read = in.read(buff)) != -1) {
	                jsonResults.append(buff, 0, read);
	            }
	        } catch (MalformedURLException e) {
	            Log.e("Error", "Error processing Places API URL", e);
	        } catch (IOException e) {
	            Log.e("Error", "Error connecting to Places API", e);
	        } finally {
	            if (conn != null) {
	                conn.disconnect();
	            }
	        }

	        try {	
	            // Create a JSON object hierarchy from the results
	            JSONObject jsonObj = new JSONObject(jsonResults.toString());
	            JSONArray resultsJsonArray = jsonObj.getJSONArray("results");
	            
	            places =new ArrayList<Place>(resultsJsonArray.length());
	            
	            for (int i = 0; i < resultsJsonArray.length(); i++) {
	                Place poi = new Place();
	                poi.name = resultsJsonArray.getJSONObject(i).getString("name");
	                poi.iconUrl = resultsJsonArray.getJSONObject(i).getString("icon");
	                JSONObject geometry = resultsJsonArray.getJSONObject(i).getJSONObject("geometry");
	                JSONObject location = geometry.getJSONObject("location");
	                poi.latitude = location.getDouble("lat");
	                poi.longitude = location.getDouble("lng");
	                places.add(poi);
	            }
	            
	        } catch (JSONException e) {
	            Log.e("Error", "Cannot process JSON results", e);
	        }
	        return places;
		}
		@Override
		protected void onPostExecute(ArrayList<Place> pois) {
			if(pois != null){
				for(Place p: pois){
					map.addMarker(new MarkerOptions()
			        .position(new LatLng(p.latitude, p.longitude))
			        .title(p.name));
				}
			}
		}
    }
	public class DeleteFavoriteTask extends AsyncTask<String, Void, Boolean> {
		@Override
		protected Boolean doInBackground(String... params) {

			String favoriteName = params[0];
			
			HttpClient httpclient = new DefaultHttpClient();
			//String url = "http://softeng.cs.uwosh.edu/students/cs342g3/favorite.php?uid=6&name=" + favoriteName + "&lat=" + latitude + "&long=" + longitude;
			String fragment = "uid=6&name=" + favoriteName;
			URI uri = null;
			try {
				uri = new URI(
						"http",
						"softeng.cs.uwosh.edu",
						"/students/cs342g3/deleteFavorite.php",
						fragment,
						null
						);
			} catch (URISyntaxException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			String request = uri.toASCIIString();
			
			// Prepare a request object
			//HttpGet httpget = new HttpGet(url); 
			HttpGet httpget = new HttpGet(request);
			HttpResponse response;
			try {
				response = httpclient.execute(httpget);
				Log.i("HTTPResponse",response.getStatusLine().toString());
				HttpEntity entity = response.getEntity();
				if (entity != null) {
					InputStream instream = entity.getContent();
					final String responsetext = Utilities.streamToString(instream);
					runOnUiThread(new Runnable(){
						@Override
						public void run() {
							// TODO Auto-generated method stub
							Toast.makeText(MapActivity.this, responsetext, Toast.LENGTH_SHORT).show();
						}
					});
					instream.close();
				}
			} catch (Exception e) {}

			// TODO: any local db stuff that may be needed

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {

		}
		@Override
		protected void onCancelled() {

		}
	}
	
	public class AddFavoriteTask extends AsyncTask<String, Void, Boolean> {
		@Override
		protected Boolean doInBackground(String... params) {

			String favoriteName = params[0];
			String oldName = params[1];
			String latitude = params[2];
			String longitude = params[3];

			HttpClient httpclient = new DefaultHttpClient();
			//String url = "http://softeng.cs.uwosh.edu/students/cs342g3/favorite.php?uid=6&name=" + favoriteName + "&lat=" + latitude + "&long=" + longitude;
			String fragment = "uid=" + userId + "&name=" + favoriteName + "&oldname=" + oldName + "&lat=" + latitude + "&long=" + longitude;
			URI uri = null;
			try {
				uri = new URI(
						"http",
						"softeng.cs.uwosh.edu",
						"/students/cs342g3/favorite.php",
						fragment,
						null
						);
			} catch (URISyntaxException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			String request = uri.toASCIIString();
			
			// Prepare a request object
			//HttpGet httpget = new HttpGet(url); 
			HttpGet httpget = new HttpGet(request);
			HttpResponse response;
			try {
				response = httpclient.execute(httpget);
				Log.i("HTTPResponse",response.getStatusLine().toString());
				HttpEntity entity = response.getEntity();
				if (entity != null) {
					InputStream instream = entity.getContent();
					final String responsetext = Utilities.streamToString(instream);
					runOnUiThread(new Runnable(){
						@Override
						public void run() {
							// TODO Auto-generated method stub
							Toast.makeText(MapActivity.this, responsetext, Toast.LENGTH_SHORT).show();
						}
					});
					instream.close();
				}
			} catch (Exception e) {}

			// TODO: any local db stuff that may be needed

			return true;
		}

		@Override
		protected void onPostExecute(final Boolean success) {

		}
		@Override
		protected void onCancelled() {

		}
	}
	public class UpdateGPSCoords extends AsyncTask<String, Void, String> {
		@Override
		protected String doInBackground(String... params) {
			
			//Get coords
        	Criteria criteria = new Criteria();
    		String provider = service.getBestProvider(criteria, false);
        	Location location = service.getLastKnownLocation(provider);
    		double latitude =  location.getLatitude();
    		double longitude = location.getLongitude();
    		
			HttpClient httpclient = new DefaultHttpClient();
			String url = "http://softeng.cs.uwosh.edu/students/cs342g3/updateUserLocationByUserId.php?userId=" + userId + "&latitude=" + latitude+"&longitude="+longitude;

		    // Prepare a request object
		    HttpGet httpget = new HttpGet(url); 
		    HttpResponse response;
		    try {
		        response = httpclient.execute(httpget);
		        HttpEntity entity = response.getEntity();
		        if (entity != null) {
		            InputStream instream = entity.getContent();
		            instream.close();
		        }
		    } catch (Exception e) {}
		    
		    return null;
		}
	}
	
	/**
	 * Represents an asynchronous task used to get user favorites
	 */
	public class GetFavoritesTask extends AsyncTask<Void, Void, Boolean> {
		
		HashMap<String, LatLng> favorites = new HashMap<String, LatLng>();

		@Override
		protected Boolean doInBackground(Void... params) {
			
			HttpClient httpclient = new DefaultHttpClient();
			
			String fragment = "uid=" + userId;
			URI uri = null;
			try {
				uri = new URI(
						"http",
						"softeng.cs.uwosh.edu",
						"/students/cs342g3/getFavorites.php",
						fragment,
						null
						);
			} catch (URISyntaxException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			
			// Prepare a request object
			HttpGet httpget = new HttpGet(uri); 
			HttpResponse response;
			try {
				response = httpclient.execute(httpget);
				Log.i("HTTPResponse",response.getStatusLine().toString());
				HttpEntity entity = response.getEntity();
				if (entity != null) {
					InputStream instream = entity.getContent();
					String favoritesAsString = Utilities.streamToString(instream);
					processFavorites(favoritesAsString);
					instream.close();
				}
			} catch (Exception e) {}

			return true;
		}

		private void processFavorites(String favoritesString){
			String[] favoritesSplit = favoritesString.split(";");
			for(String favorite : favoritesSplit){
				String[] thisFavorite = favorite.split(":");
				String name = thisFavorite[0];
				double latitude = Double.parseDouble(thisFavorite[1]);
				double longitude = Double.parseDouble(thisFavorite[2]);
				LatLng ll = new LatLng(latitude, longitude);
				favorites.put(name, ll);
			}
		}

		@Override
		protected void onPostExecute(final Boolean success) {
			for(String favorite : favorites.keySet()){
				LatLng ll = favorites.get(favorite);
				map.addMarker(new MarkerOptions()
				.position(ll)
				.title(favorite)
				.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW)));
			}
		}
	}
	
	public class GetFriendLocationsTask extends AsyncTask<Void, Void, Response<FriendLocation>> {
		@Override
		protected Response<FriendLocation> doInBackground(Void... params) {

			HttpURLConnection connection = null;
			HttpResponse response = null;
			
			ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); // must be created from activity and passed in
			if (Utilities.isNetworkAvailable(connectivityManager)) {
				try {
					HttpClient httpclient = new DefaultHttpClient();
					HttpPost httppost = new HttpPost("http://softeng.cs.uwosh.edu/students/cs342g3/getFriendLocations.php?userId=" + userId);
					response = httpclient.execute(httppost);
				} catch (MalformedURLException e) {
					System.out.println("Bad URL");
				} catch (IOException e) {
					System.out.println("Unable to retrieve web page");
				} finally {
					if (connection != null)
						connection.disconnect();
				}
			}
			
			HttpEntity r_entity = response.getEntity();
			String xmlString = "";

			try {
				xmlString = EntityUtils.toString(r_entity);
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("xml:" + xmlString);
			ByteArrayInputStream xml = new ByteArrayInputStream(xmlString.getBytes());

			FriendLocationParser fp = new FriendLocationParser();

			Response<FriendLocation> friends = new Response<FriendLocation>();
			try {
				friends = fp.parse(xml);
			} catch (XmlPullParserException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			return friends;
		}

		@Override
		protected void onPostExecute(Response<FriendLocation> l) {
			fl = new ArrayList<FriendLocation>();
			for (FriendLocation fr: l.list) {
				System.out.println("Adding " + fr.toString());
				fl.add(fr);
				map.addMarker(new MarkerOptions()
		        .position(new LatLng(fr.lat, fr.lng))
		        .title(fr.name)
		        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
			}
		}
	}
	
	private Runnable doRepeatEvent = new Runnable() {
		@SuppressLint("NewApi")
		public void run(){
			System.out.println("Doing task");
			map.clear();
			new UpdateGPSCoords().execute();
			new loadLocalPOIs().execute();
			new GetFriendLocationsTask().execute();
			new GetFavoritesTask().execute();
			mRepeatEvent.postDelayed(doRepeatEvent, REPEAT_EVENT);
		}
	};
}

